package com.wgz.medicalmanagement.controller;

import com.wgz.medicalmanagement.common.entity.Result;
import com.wgz.medicalmanagement.domain.dto.LoginRequest;
import com.wgz.medicalmanagement.domain.dto.RegisterRequest;
import com.wgz.medicalmanagement.domain.entity.User;
import com.wgz.medicalmanagement.domain.vo.LoginResponse;
import com.wgz.medicalmanagement.domain.vo.UserInfoVO;
import com.wgz.medicalmanagement.service.UserService;
import jakarta.servlet.http.HttpServletRequest;
import jakarta.validation.Valid;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.*;

import java.util.concurrent.TimeUnit;
import java.util.Map;

/**
 * 用户控制器
 *
 * @author medical
 * @since 2023-05-29
 */
@Slf4j
@RestController
@RequestMapping("/api/auth")
@RequiredArgsConstructor
public class UserController {

    private final UserService userService;
    private final RedisTemplate<String, Object> redisTemplate;
    private final HttpServletRequest request;

    /**
     * 用户登录
     *
     * @param loginRequest 登录请求
     * @return 登录响应
     */
    @PostMapping("/login")
    public ResponseEntity<Result<LoginResponse>> login(@Valid @RequestBody LoginRequest loginRequest) {
        log.info("用户登录: {}", loginRequest.getUsername());
        try {
            LoginResponse loginResponse = userService.login(loginRequest);
            return ResponseEntity.ok(Result.success("登录成功", loginResponse));
        } catch (Exception e) {
            log.error("登录失败: {}", e.getMessage());
            return ResponseEntity.badRequest().body(Result.fail("登录失败: " + e.getMessage()));
        }
    }

    /**
     * 用户注册
     *
     * @param registerRequest 注册请求
     * @return 注册结果
     */
    @PostMapping("/register")
    public ResponseEntity<Result<User>> register(@Valid @RequestBody RegisterRequest registerRequest) {
        String clientIp = getClientIp();
        String username = registerRequest.getUsername();
        log.info("用户注册: {}, IP: {}", username, clientIp);
        
        // IP限流 - 防止同一IP短时间内多次注册
        String ipLimitKey = "register:ip_limit:" + clientIp;
        try {
            Long ipCount = redisTemplate.opsForValue().increment(ipLimitKey, 1);
            if (ipCount == 1) {
                // 第一次访问，设置过期时间
                redisTemplate.expire(ipLimitKey, 60, TimeUnit.SECONDS);
            } else if (ipCount != null && ipCount > 3) {
                // 1分钟内超过3次请求
                log.warn("IP: {} 注册请求过于频繁", clientIp);
                return ResponseEntity.badRequest().body(Result.fail("操作过于频繁，请稍后再试"));
            }
        } catch (Exception e) {
            // Redis错误，记录日志但允许继续
            log.warn("Redis限流检查失败: {}", e.getMessage());
        }
        
        // 用户名防重复提交 - 控制器层面的快速检查
        String userRegLockKey = "controller:register:" + username;
        try {
            Boolean userLock = redisTemplate.opsForValue().setIfAbsent(userRegLockKey, "1", 5, TimeUnit.SECONDS);
            if (userLock != null && !userLock) {
                log.warn("用户 {} 注册请求重复提交", username);
                return ResponseEntity.badRequest().body(Result.fail("请勿重复提交注册请求"));
            }
        } catch (Exception e) {
            // Redis错误，记录日志但允许继续
            log.warn("Redis注册锁检查失败: {}", e.getMessage());
        }
        
        try {
            User user = userService.register(registerRequest);
            return ResponseEntity.ok(Result.success("注册成功", user));
        } catch (Exception e) {
            log.error("注册失败: {}", e.getMessage());
            
            // 对常见错误进行友好提示
            String errorMessage = e.getMessage();
            if (errorMessage.contains("Duplicate entry") && errorMessage.contains("username")) {
                return ResponseEntity.badRequest().body(Result.fail("用户名已被使用，请尝试其他用户名"));
            } else if (errorMessage.contains("注册操作正在处理中")) {
                return ResponseEntity.badRequest().body(Result.fail("请勿重复提交注册请求"));
            } else if (errorMessage.contains("密码不一致")) {
                return ResponseEntity.badRequest().body(Result.fail("两次输入的密码不一致"));
            } else if (errorMessage.contains("用户名已存在")) {
                return ResponseEntity.badRequest().body(Result.fail("用户名已存在，请更换用户名"));
            }
            
            return ResponseEntity.badRequest().body(Result.fail("注册失败: " + e.getMessage()));
        } finally {
            // 清理控制器锁
            try {
                redisTemplate.delete(userRegLockKey);
            } catch (Exception e) {
                log.warn("删除Redis注册锁失败: {}", e.getMessage());
            }
        }
    }

    /**
     * 获取客户端真实IP
     * 
     * @return 客户端IP
     */
    private String getClientIp() {
        String ipAddress = request.getHeader("X-Forwarded-For");
        if (ipAddress == null || ipAddress.isEmpty() || "unknown".equalsIgnoreCase(ipAddress)) {
            ipAddress = request.getHeader("Proxy-Client-IP");
        }
        if (ipAddress == null || ipAddress.isEmpty() || "unknown".equalsIgnoreCase(ipAddress)) {
            ipAddress = request.getHeader("WL-Proxy-Client-IP");
        }
        if (ipAddress == null || ipAddress.isEmpty() || "unknown".equalsIgnoreCase(ipAddress)) {
            ipAddress = request.getRemoteAddr();
        }
        
        // 对于通过多个代理的情况，第一个IP为客户端真实IP
        if (ipAddress != null && ipAddress.contains(",")) {
            ipAddress = ipAddress.split(",")[0].trim();
        }
        
        return ipAddress;
    }

    /**
     * 检查用户名是否可用
     *
     * @param usernameRequest 包含用户名的请求对象
     * @return 检查结果
     */
    @PostMapping("/check-username")
    public ResponseEntity<Result<Boolean>> checkUsername(@RequestBody Map<String, String> usernameRequest) {
        try {
            String username = usernameRequest.get("username");
            if (username == null || username.trim().isEmpty()) {
                return ResponseEntity.badRequest().body(Result.fail("用户名不能为空"));
            }
            
            boolean exists = userService.existsByUsername(username);
            if (exists) {
                return ResponseEntity.ok(Result.fail("用户名已存在"));
            } else {
                return ResponseEntity.ok(Result.success("用户名可用", true));
            }
        } catch (Exception e) {
            log.error("检查用户名失败: {}", e.getMessage());
            return ResponseEntity.badRequest().body(Result.fail("检查用户名失败: " + e.getMessage()));
        }
    }

    /**
     * 获取当前用户信息
     *
     * @return 用户信息
     */
    @GetMapping("/user-info")
    public ResponseEntity<Result<UserInfoVO>> getUserInfo() {
        try {
            UserInfoVO userInfo = userService.getCurrentUserInfo();
            return ResponseEntity.ok(Result.success(userInfo));
        } catch (Exception e) {
            log.error("获取用户信息失败: {}", e.getMessage());
            return ResponseEntity.badRequest().body(Result.fail("获取用户信息失败: " + e.getMessage()));
        }
    }

    /**
     * 用户注销
     *
     * @return 注销结果
     */
    @PostMapping("/logout")
    public ResponseEntity<Result<Void>> logout() {
        try {
            userService.logout();
            return ResponseEntity.ok(Result.success("注销成功", null));
        } catch (Exception e) {
            log.error("注销失败: {}", e.getMessage());
            return ResponseEntity.badRequest().body(Result.fail("注销失败: " + e.getMessage()));
        }
    }
} 